#ifndef INCLUDE_BAMBOO_CONST_H_
#define INCLUDE_BAMBOO_CONST_H_
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include "math.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <pthread.h>
#include <unistd.h>

#define LOGTAG
#ifdef LOGTAG
#define LOGI(level, format, ...) Logtrace::m_logTrace(level, "[%s@%s,%d]: " format "\n", __func__, __FILE__, __LINE__, ##__VA_ARGS__);
#define LOGE(format, ...) Logtrace::m_logTrace(LEVEL_MAX, "[%s@%s,%d]: " format "\n", __func__, __FILE__, __LINE__, ##__VA_ARGS__);
#define LOG(format, ...) Logtrace::m_logNoFormatTrace(format "\n", ##__VA_ARGS__);
#define LOGMAT(mat, lda, n, m, p, q, ball, msg) Logtrace::m_logMatrix(mat, lda, n, m, p, q, ball, msg);
#define LOGSTAT(newline, format, ...) Logtrace::m_logStat(newline, format, ##__VA_ARGS__);
#define LOGSTATINFO(format, ...) Logtrace::m_logStatInfo(format "\n", ##__VA_ARGS__);
#define LOGPRINT(format, ...) Logtrace::m_logPrint("[%s@%s,%d]:" format "\n", __func__, __FILE__, __LINE__, ##__VA_ARGS__);
#else
#define LOG(format, ...)
#endif
    #define RTCM2PREAMB ((const unsigned char) 0x66) /* rtcm ver.2 frame preamble */
    #define RTCM3PREAMB  ((const unsigned char) 0xD3) /* rtcm ver.3 frame preamble */
    #define ATOMPREAMB  ((const unsigned char) 0xDB)  /* atom preamble */
    #define MAXFREQ 7
    #define MAXSYS 8
    #define MAXSAT 160
    #define MAXSIT 1 // 600
    #define MAXOC 120
    #define MAXOBSTYP 100
    #define MAXPORT 10
    #define MAXICS 21
    #define MAXECLIP 120
    #define MAXCOEFPAR 3 + MAXSYS + 1 + 1 + 2 + MAXSYS // XYZ RECCLK ZTD AMB ION DCB (ION maybe two,DCB is maxsys)
    #define MAXDGR 7
    #define MAXPNT 2 * (MAXDGR + 1)
    #define MAXVARS 3 * (MAXICS + 1)
    #define MAXORBEPHTYPE 8

    #define MINCMNSIT 4
    #define MAX_GRID 73
    #define MeanEarthRadius 6371000
    #define IONO_SHELL_H 450000
    #define MAXTABLE 20
    #define MAXBASE 20

    static char SYS[] = "GRECBSJI";/// for BDS-3
    #define MAXWND 1E-2
    static char OBSTYPE[MAXSYS][MAXFREQ][32] = { // WPCIXSAQLDBYMZN  //"WPCIXSAQLDBYMZN ";
        {                                       //G:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "}},
        {//R:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "}},
        {//E:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN"},
         {"WPCIXSAQLDBYMZN "}},
        {//C:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "}},
        {//S:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "}},
        {//J:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "}},
        {//I:
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "},
         {"WPCIXSAQLDBYMZN "}} };
    #define PI 3.1415926535897932384626433832795028841971693993
    #define VEL_LIGHT 299792458.0
    #define E_MAJAXIS 6378136.60

    #define DEG2RAD PI / 180.0
    #define RAD2DEG 180.0 / PI

    #define ARCSEC2RAD PI / (3600.0 * 180.0)
    #define CONE 2.7182818284590452353602874713526624977572470936999

    #define EARTH_A 6378137
    #define EARTH_ALPHA 1 / 298.257223563
    #define ESQUARE (EARTH_A * EARTH_A - (EARTH_A - EARTH_A * EARTH_ALPHA) * (EARTH_A - EARTH_A * EARTH_ALPHA)) / (EARTH_A * EARTH_A)

    #define OFF_GPS2TAI 19.0
    #define OFF_TAI2TT 32.184
    #define OFF_GPS2TT OFF_GPS2TAI + OFF_TAI2TT
    #define OFF_MJD2JD 2400000.50

    #define E_ROTATE 7.2921151467E-5
    #define GME 3.986004415E14; //TT-compatible
    #define GPS_FREQ 10230000.0
    #define GPS_L1 154 * GPS_FREQ
    #define GPS_L2 120 * GPS_FREQ
    #define GPS_L5 115 * GPS_FREQ

    #define GLS_FREQ 178000000.0
    #define GLS_L1 9 * GLS_FREQ
    #define GLS_L2 7 * GLS_FREQ
    #define GLS_dL1 562500.0
    #define GLS_dL2 437500.0

    #define GAL_E1 GPS_L1
    #define GAL_E5 1191795000.0
    #define GAL_E5a GPS_L5
    #define GAL_E5b 1207140000.0
    #define GAL_E6 1278750000.0

    #define BDS_B1 1561098000.0
    #define BDS_B2b 1207140000.0
    #define BDS_B3 1268520000.0
    #define BDS_B1c 1575420000.0
    #define BDS_B2a 1176450000.0
    #define BDS_B2 1191795000.0
    #define QZS_L1 GPS_L1
    #define QZS_L2 GPS_L2
    #define QZS_L5 GPS_L5
    #define QZS_LEX 1278750000.0

    //  #define SNRCONST_FREQ1[3] {0.00224,0.00077,0.00224};
    #define SNRCONST_FREQ1[3] { 1.61 * 10e-5, 1.61 * 10e-5, 1.61 * 10e-5 };

    #define LEN_OBSTYPE 4
    #define LEN_FREQ 4
    #define LEN_ANTENNA 21
    #define LEN_PRN 4
    #define LEN_PORT 256
    #define LEN_STRING 1024
    #define LEN_SATTYPE 20
    #define LEN_PCVTYPE 5
    #define LEN_CLKTYPE 5
    #define LEN_COSPARID 16
    #define LEN_SITENAME 5
    #define LEN_ZTDMAP 3
    #define LEN_EPHION 4

    #define ORB_NONE 0;
    #define CLK_NONE 0;
    #define ORB_BRD 1;
    #define CLK_BRD 1;
    #define ORB_SP3 2;
    #define CLK_SP3 2;
    #define ORB_SSR 3;
    #define CLK_SSR 3;

    #define PRO_PPP 0
    #define PRO_CLK 1
    #define PRO_RTK 2
    #define PRO_NRTK 3
    #define PRO_VRS 4
    #define PRO_RTORB 5

    #define PRO_EXTUPD_WL 6
    #define PRO_SMUPD_WL 7

    #define PRO_EXTFCB_NL 8
    #define PRO_VISUAL 9
    #define PRO_QC 10
    #define PRO_ESTIFCB 11

    #define LEVEL_IO 0    //
    #define LEVEL_GNSS 1  //
    #define LEVEL_FRAME 2 //
    #define LEVEL_ALGO 3 //
    #define LEVEL_MAX 4

    #define ToHandle 0; //
    #define ToWait 1;   //
    #define DataTOut 2; //
    #define DataOutT 3; //
    #define DataNEx 4;  //
    #define DataErr 5;  //
    #define DataCmpl 6; //

    #define NetClose -1; //
    #define NetCont 0;   //
    #define NetTOut 1;   //
    #define NetUAuth 2;  //
    #define NetAuth 3;   //

    /*** AMBIGUITY STATE ****/
    #define AMBTYPE_NONE 0;
    #define AMBTYPE_EWL 1;
    #define AMBTYPE_EWLCOMB 2;
    #define AMBTYPE_WL 3;
    #define AMBTYPE_IF 4;
    #define AMBTYPE_RAW 5;

    #define LEVEL_TRACE LEVEL_IO;
    #define LEVEL_ERROR LEVEL_MAX;

    #define str_tracetype[][16] { "IO", "GNSS", "FRAME", "ALGO", "ERROR" }

    #define AMB_FIX 4;    //
    #define AMB_WLFIX 3;  //
    #define AMB_EWLFIX 2; //
    #define AMB_EST 1;    //
    #define AMB_INIT 0;   //
#ifdef _WIN32
#define def_thread_t HANDLE
#define def_dev_t HANDLE
#define def_cond_t CONDITION_VARIABLE
#define def_lock_t CRITICAL_SECTION
#define def_initlock(f) InitializeCriticalSection(f)
#define def_lock(f) EnterCriticalSection(f)
#define def_unlock(f) LeaveCriticalSection(f)
#define def_destroylock(f) DeleteCriticalSection(f)

#define def_initcond(c) InitializeConditionVariable(c)
#define def_notify(c) WakeConditionVariable(c)
#define def_wait(c, f) SleepConditionVariableCS(c, f, INFINITE)
#define def_destroycond(c)

#define FILEPATHSEP '\\'
#define def_pthread_id_self() GetCurrentThreadId()
#else

#define def_thread_t pthread_t
#define def_dev_t int
#define def_cond_t pthread_cond_t
#define def_lock_t pthread_mutex_t
#define def_initlock(f) pthread_mutex_init(f, NULL)
#define def_lock(f) pthread_mutex_lock(f)
#define def_unlock(f) pthread_mutex_unlock(f)
#define def_destroylock(f) pthread_mutex_destroy(f)

#define def_initcond(c) pthread_cond_init(c, NULL)
#define def_notify(c) pthread_cond_signal(c)
#define def_wait(c, f) pthread_cond_wait(c, f)
#define def_destroycond(c) pthread_cond_destroy(c)

#define FILEPATHSEP '/'

#define def_pthread_id_self() pthread_self()
#endif

#define BDSTOINT(type, value) (type)(round(value))

#define BDSADDBITS(a, b)                                                               \
    {                                                                                  \
        bitbuffer (bitbuffer << (a)) | (BDSTOINT(long long, b) & ((1ULL << a) - 1)); \
        numbits += (a);                                                                \
        while (numbits >= 8)                                                           \
        {                                                                              \
            buffer[size++] bitbuffer >> (numbits - 8);                               \
            numbits -= 8;                                                              \
        }                                                                              \
    }

#define BDSADDBITSFLOAT(a, b, c)                      \
    {                                                 \
        long long i BDSTOINT(long long, (b) / (c)); \
        BDSADDBITS(a, i)                              \
    };

#define bbo_if(isys, l1) pointer_charstr(MAXFREQ, LEN_FREQ, (char *)dly->freq_obs[isys], l1)

//******** Inline Function ********//
static inline double ABS(double a) {
    return a > 0 ? a : -a;
}
static inline double MIN(double a, double b) {
    return a > b ? b : a;
}
static inline double SIGN(double a, double b) {
    return b > 0 ? a : -a;
}
static inline int NINT(double a) {
    return (int)(a + SIGN(1, a) * 0.5);
}



#endif /* INCLUDE_BAMBOO_CONST_H_ */
